深入ES6 (六) Proxy

Proxy

Proxy在英文中的意思是代理的意思,而在ES6中的意义可不像是代理,而像是拦截:”intercept”。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

proxy的用法

1
var proxy = new Proxy(target, handler);

上面这串代码的意思是给target这个对象加一层拦截,或者叫代理,而代理的限制规则为handler,new Proxy代表新生成一个实例

1
2
3
4
5
6
7
8
9
var proxy = new Proxy({}, {
get: function(target, property) {
return 35;
}
});
proxy.tezml // 35
proxy.name // 35
proxy.age // 35

上面这块代码的意思是给{}(空对象)增加个限制,这个限制方法叫get(下面对提及到),导致的结果是无论获取实例的任何属性都会先通过get中的函数。

property作为参数允许我们传递一个json,json中可以传递各种方法,下面来具体介绍有哪些方法。

1、get(target, property)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var person = {
name: "张三"
};
var proxy = new Proxy(person, {
get: function(target, property) {
if (property in target) {
return target[property];
} else {
return "警告"
}
}
});
proxy.name // "张三"
proxy.age // "警告"

get方法用于拦截某个属性的读取操作
get允许2个参数,第一个参数target是原对象被选中的属性,property是当前选中的属性

2、set(target, prop, value)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let validator = {
set: function(target, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
if (value > 200) {
throw new RangeError('The age seems invalid');
}
}
// 对于age以外的属性,直接保存
target[prop] = value;
}
};
let person = new Proxy({}, validator);
person.age = 100;
person.age // 100
person.age = 'young' // 报错
person.age = 300 // 报错

set方法用于拦截某个属性的赋值操作
set中,target代表原对象,prop代表要修改的属性,value则是要被赋的值

3、apply()

1
2
3
4
5
6
7
8
9
10
11
var target = function () { return 'I am the target'; };
var handler = {
apply: function () {
return 'I am the proxy';
}
};
var p = new Proxy(target, handler);
p()
// "I am the proxy"

apply方法用于拦截函数调用


以上这三个方法是我认为前端开发中可能会用到的方法,而其实proxy还有很多的方法比如拦截new,拦截数据类型等等,具体详解请参考:阮一峰大神详解

其他方法不在这里详解并不是因为它们没有用,而是我个人认为这些方法在用于底层框架或者客户端服务中会显示出它们的威力,而前端业务开发中用到的并不多。

Proxy的this

1
var proxy = new Proxy(target, handler);

Proxy只是一层代理,而proxy中的this依然指向proxy,既不是target,也不会是handler